package com.penglecode.netty3.example3;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ApplicationClient {

	private static final Logger logger = LoggerFactory.getLogger(ApplicationClient.class);
	
	private static final ChannelFactory channelFactory = new NioClientSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool());
	
	private static final ClientBootstrap clientBootstrap = new ClientBootstrap(channelFactory);
	
	private InetSocketAddress remoteAddress;
	
	private int port;
	
	private Channel channel;
	
	static {
		clientBootstrap.setOption("connectTimeoutMillis", 3000);
		clientBootstrap.setOption("tcpNoDelay", true);
		clientBootstrap.setOption("keepAlive", true);
		clientBootstrap.setPipelineFactory(new ClientChannelPipelineFactory());
	}

	public ApplicationClient(int port) throws Exception {
		super();
		this.port = port;
		this.remoteAddress = new InetSocketAddress(InetAddress.getLocalHost(), port);
		ChannelFuture channelFuture = clientBootstrap.connect(remoteAddress);
		this.channel = channelFuture.getChannel();
		/*channelFuture.awaitUninterruptibly(); //因为是异步的,所以要等待服务器端的响应
		if(channelFuture.isCancelled()){
			logger.warn("Connection attempt cancelled by user!");
		}else if(!channelFuture.isSuccess()){
			logger.warn("Connection established failure!", channelFuture.getCause());
		}
		//获取channel关闭时被唤醒的ChannelFuture  
        //无论future是否成功都会返回CloseFuture，失败的时候会自动关闭Channel
		channelFuture.getChannel().getCloseFuture().awaitUninterruptibly(); //如果handler中不手动调用channel.close()那么此处在getCloseFuture()处等待
		channelFactory.releaseExternalResources(); // 可以看下源码,此句代码等效于bootstrap.shutdown()
*/	}
	
	public void executeCommand(ApplicationCommand command){
		channel.write(command);
	}
	
	public static void main(String[] args) throws Exception {
		ApplicationClient client = new ApplicationClient(9000);
		ApplicationCommand command = new ApplicationCommand();
		command.setSerialNo(String.valueOf(System.currentTimeMillis()));
		command.setServiceClass("com.penglecode.foo.FooService");
		command.setInvokeMethod("execute");
		System.out.println(">>> command = " + command);
		client.executeCommand(command);
	}
}
